/*******************************************************************************
 *
 * Creator: Jose Castillo jocasal@gmail.com
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL DANIEL MURPHY BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/
/**
 * Created at 25 Mar, 2011
 */
package packbridge;

import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.Fixture;
import org.jbox2d.dynamics.FixtureDef;
import org.jbox2d.dynamics.World;
import org.jbox2d.dynamics.contacts.Contact;
//import org.jbox2d.testbed.framework.ContactPoint;
//import org.jbox2d.testbed.framework.TestbedSettings;
//import org.jbox2d.testbed.framework.TestbedTest;

/**
 * @author jose
 */
public class EBridge extends TestbedTest {
	private boolean firstTime = true;
        final float dwidth = 0.50f;
        final float dheight = 1.0f;
        float ddensity = 4000f;
        final float dfriction = 0.9f;
        public Fixture m_sensor,m_sensor2,m_sensor3,m_sensor4; //sensor del rio, del final y los de los lados
      Puente p;
      coche c;
      Generacion g;
      int poblacion = 25;
      int individuo;
      double t_inicial; // el tiempo inicial
      int generaciones;


      public EBridge(){
       g = new Generacion(poblacion);
       individuo = 0;
       generaciones=0;
       Puente.n_absoluto=0; //cada puente tendrá un identificador, esto sirve de contrador
      }


    public void Crear_ladrillos(float ancho, float alto, float x, float y, float angulo, boolean horizontal) {

    	PolygonShape sd = new PolygonShape();
        sd.setAsBox(.5f*ancho, .5f*alto);
        FixtureDef fd = new FixtureDef();
        fd.shape = sd;
        fd.density = ddensity;
        BodyDef bd = new BodyDef();
        bd.type = BodyType.DYNAMIC;
        fd.friction = dfriction;
        fd.restitution = 0.05f;
        bd.position = new Vec2(x, y);
        bd.userData="ladrillo";
        bd.angle = angulo;
        Body myBody = m_world.createBody(bd);
        myBody.createFixture(fd);

    }

	
	@Override
	public void initTest() {
		if (firstTime) {
			setCamera(0f, 12f, 10f);
			firstTime = false;
		}

        
            PolygonShape sd = new PolygonShape();
            sd.setAsBox(50.0f, 10.0f);

            BodyDef bdf = new BodyDef();
            bdf.position = new Vec2(0.0f, -10.0f);
            bdf.userData = "suelo";

            m_world.createBody(bdf).createFixture(sd, 0f);

            sd.setAsBox(60.0f, 10.0f);
            BodyDef bdlimit = new BodyDef();
            bdlimit.position = new Vec2(2.0f, 47.0f);
            bdlimit.angle=-0.4f;
            bdlimit.userData = "suelo";
            FixtureDef fd = new FixtureDef();
            fd.shape=sd;
            fd.isSensor = true;
        //    fd.filter.groupIndex=-1;

            Body b = m_world.createBody(bdlimit);
            m_sensor = b.createFixture(fd);
            



            //m_world.
            BodyDef bd = new BodyDef();
            sd.setAsBox(15.0f, 50.0f);
            bd.position = new Vec2(-65.0f,30.0f);
            
            m_world.createBody(bd).createFixture(sd, 0f);

            sd.setAsBox(5.0f, 47.0f);
            bd.userData = "pared";
            bd.position = new Vec2(55.0f,27.0f);
            m_world.createBody(bd).createFixture(sd, 0f);

            sd.setAsBox(5.0f, 50.0f);
            bd.userData = null;
            bd.position = new Vec2(-85.0f,50.0f);
            m_world.createBody(bd).createFixture(sd, 0f);

            sd.setAsBox(5.0f, 50.0f);
            bd.userData = "fin";
            bd.position = new Vec2(65.0f,50.0f);
            m_world.createBody(bd).createFixture(sd, 0f);


// sensor del final arriba
             sd.setAsBox(5.2f, 50.0f);
            FixtureDef fd2 = new FixtureDef();
            fd2.shape=sd;
            fd2.isSensor = true;
            //bd.userData = "fin";
            bd.position = new Vec2(65.0f,150.0f);
            Body b2= m_world.createBody(bd);
             m_sensor2 = b2.createFixture(fd2);

             // sensor de dentro delante

             bd.position = new Vec2(-60.0f,25.0f);
             bd.userData="limite";
            Body b3= m_world.createBody(bd);
             m_sensor3 = b3.createFixture(fd2);

             // sensor de dentro detras

              bd.position = new Vec2(60.0f,20.0f);
             bd.userData="limite";
            Body b4= m_world.createBody(bd);
             m_sensor4 = b4.createFixture(fd2);

             // llamamos a la primera generacion
              generacion();
      
	}

        public void generacion(){

             p = g.individuos[individuo];

          for(int i=0; i<20; i++){

               Crear_ladrillos(p.genes[i][2],p.genes[i][3],p.genes[i][0],p.genes[i][1], p.genes[i][4], true);
              // System.out.println("-");
            }

         c = new coche();
         c.world = m_world;
         c.init();

         t_inicial = System.currentTimeMillis();
        

        }

        public void reiniciar(){

            if(individuo<poblacion-1)
            {
             individuo++;
            } else
            {
              individuo =0;
              g.cruzarymutar();
              generaciones++;
              System.out.println("---Nueva Generacion -- "+generaciones);
          }

          init(m_debugDraw);

        }

         @Override
        public void step(TestbedSettings settings) {

             super.step(settings);
             double t_final= System.currentTimeMillis();

      
             if((t_final - t_inicial)> 15000) //si se pasa del tiempo
             {
                 p.duracion = 30000;
                 p.distancia = c.wheel1.getWorldCenter().x;
                 p.calcularfitness();
                 reiniciar();
             }




             for (int i = 0; i < m_pointCount; ++i) {
                        ContactPoint point = points[i];
                        Body body1 = point.fixtureA.getBody();
                        Body body2 = point.fixtureB.getBody();

                        if(body1.m_userData != null && body2.m_userData != null){
                        String sb1 = (String) body1.m_userData;
                        String sb2 = (String) body2.m_userData;
                        if((sb1.equals("fin") || sb2.equals("fin"))){
                            if(c.wheel1.getWorldCenter().x >= 55) {
                                p.duracion = t_final - t_inicial;
                                p.distancia = c.wheel1.getWorldCenter().x;
                                p.calcularfitness();
                                p.fitness+=50;
                                reiniciar();
                            }
                        }

                         if((sb1.equals("pared") || sb2.equals("pared"))){ //si toca la pared del fondo
                             if(sb1.equals("coche") || sb2.equals("coche") ){
                                p.f_altura = (int) (c.wheel1.getWorldCenter().y - 51);
                             }
                         }
                        }
             }

        }


         @Override

         public void beginContact(Contact contact) {
             Fixture fixtureA = contact.getFixtureA();
             Fixture fixtureB = contact.getFixtureB();
                if (((fixtureA == m_sensor)&&(fixtureB.getUserData()=="coche"))||((fixtureA == m_sensor2)&&(fixtureB.getUserData()=="coche"))) {

                    double t_final= System.currentTimeMillis();
                    p.duracion = t_final - t_inicial;
                    p.distancia = c.wheel1.getWorldCenter().x;
                    p.calcularfitness();
                    reiniciar();
                }

                if (((fixtureB == m_sensor)&&(fixtureA.getUserData()=="coche"))||((fixtureB == m_sensor2)&&(fixtureA.getUserData()=="coche"))) {

                    double t_final= System.currentTimeMillis();
                    p.duracion = t_final - t_inicial;
                    p.distancia = c.wheel1.getWorldCenter().x;
                    p.calcularfitness();
                    reiniciar();
                }

                if(fixtureA.getUserData()=="interior" || fixtureB.getUserData()=="interior"){
                    if(fixtureA.getUserData()!="coche" && fixtureB.getUserData()!="coche"){
                        double t_final= System.currentTimeMillis();
                        p.duracion = t_final - t_inicial;
                        p.distancia = c.wheel1.getWorldCenter().x;
                        p.calcularfitness();
                        reiniciar();
                    }
                }


             if(fixtureA.getBody().getUserData()=="ladrillo" || fixtureB.getBody().getUserData()=="ladrillo") {
                  
                 if(fixtureA == m_sensor3 || fixtureB == m_sensor3 || fixtureA == m_sensor4 || fixtureB == m_sensor4)  {
                     p.duracion = 30000;
                     p.distancia = c.wheel1.getWorldCenter().x;
                     p.calcularfitness();
                     reiniciar();

                 }
             }
         }

	@Override
	public String getTestName() {
		return "Evolution Bridge";
	}

}
